package xyz.imeans.w.config;

import com.xiaoleilu.hutool.date.DateTime;
import com.xiaoleilu.hutool.date.DateUtil;
import com.xiaoleilu.hutool.util.StrUtil;
import xyz.imeans.w.annotion.AggregateKey;
import xyz.imeans.w.annotion.Column;
import xyz.imeans.w.annotion.Date;
import xyz.imeans.w.annotion.DuplicateKey;
import xyz.imeans.w.annotion.Id;
import xyz.imeans.w.annotion.LngLat;
import xyz.imeans.w.annotion.Sfzh;
import xyz.imeans.w.annotion.Tel;
import xyz.imeans.w.annotion.UniqueKey;
import xyz.imeans.w.annotion.Value;
import xyz.imeans.w.annotion.Xm;
import xyz.imeans.w.service.core.TestService;

import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.Random;
import java.util.UUID;

public class ObjCreateFactory {

    public static Map<String, Object> createObj(Class cls) throws ClassNotFoundException {
        Map<String, Object> map = new HashMap<>();
        Field[] fields = cls.getDeclaredFields();
        Map<String, String> copyMap = new HashMap<>(10);
        for (Field field : fields) {
            if(field.isAnnotationPresent(Sfzh.class)) {
                Sfzh annotation = field.getAnnotation(Sfzh.class);
                TestService service = InitCreateFactory.getService(annotation.value());
                Object value = service.createValue(annotation.sex(), annotation.provs());
                map.put(field.getName(), value);
            } else if(field.isAnnotationPresent(Xm.class)) {
                Xm annotation = field.getAnnotation(Xm.class);
                TestService service = InitCreateFactory.getService(annotation.value());
                Object value = service.createValue(annotation.type());
                map.put(field.getName(), value);
            } else if(field.isAnnotationPresent(Tel.class)) {
                Tel annotation = field.getAnnotation(Tel.class);
                TestService service = InitCreateFactory.getService(annotation.value());
                Object value = service.createValue(annotation.qh(), annotation.type());
                map.put(field.getName(), value);
            } else if(field.isAnnotationPresent(LngLat.class)) {
                LngLat annotation = field.getAnnotation(LngLat.class);
                TestService service = InitCreateFactory.getService(annotation.value());
                Object value = service.createValue(annotation.center(), String.valueOf(annotation.radius()));
                if(StrUtil.isNotBlank(annotation.type())) {
                    String[] split = ((String) value)
                            .replace("[", "").replace("]", "").split(",");
                    if("lng".equals(annotation.type())) {
                        map.put(field.getName(), split[0]);
                    } else {
                        map.put(field.getName(), split[1]);
                    }
                } else {
                    map.put(field.getName(), value);
                }
            } else if(field.isAnnotationPresent(Value.class)) {
                Value annotation = field.getAnnotation(Value.class);
                if(StrUtil.isNotBlank(annotation.copyAs())) {
                    copyMap.put(field.getName(), annotation.copyAs());
                } else if(annotation.list().length == 0) {
                    map.put(field.getName(), annotation.value());
                } else if(annotation.list().length == 1) {
                    map.put(field.getName(), annotation.list()[0]);
                } else {
                    Random random = new Random();
                    String value = annotation.list()[random.nextInt(annotation.list().length)];
                    map.put(field.getName(), value);
                }
            } else if(field.isAnnotationPresent(Date.class)) {
                Date annotation = field.getAnnotation(Date.class);
                if(annotation.internal() > 0) {
                    DateTime dateTime = DateUtil.offsetSecond(InitCreateFactory.DATE_FLAG, -1);
                    map.put(field.getName(), DateUtil.format(dateTime, annotation.format()));
                    InitCreateFactory.DATE_FLAG = dateTime;
                } else {
                    map.put(field.getName(), DateUtil.format(DateUtil.date(), annotation.format()));
                }
            } else if(field.isAnnotationPresent(Id.class)) {
                map.put(field.getName(), UUID.randomUUID().toString().replace("-", ""));
            }
        }
        for (Map.Entry<String, String> entry : copyMap.entrySet()) {
            map.put(entry.getKey(), map.get(entry.getValue()));
        }
        return map;
    }

    public static Map<String, String> getFieldColumn(Class cls) {
        Map<String, String> map = new LinkedHashMap<>();
        Field[] fields = cls.getDeclaredFields();
        for (Field field : fields) {
            if (field.isAnnotationPresent(Column.class)) {
                Column column = field.getAnnotation(Column.class);
                map.put(field.getName(), column.value());

                if(field.isAnnotationPresent(Id.class)) {
                    map.put("my_system_data_id", column.value());
                }
                if(field.isAnnotationPresent(UniqueKey.class)) {
                    map.put("my_system_data_uniqueKey", column.value());
                }
                if(field.isAnnotationPresent(AggregateKey.class)) {
                    map.put("my_system_data_aggregateKey", column.value());
                }
                if(field.isAnnotationPresent(DuplicateKey.class)) {
                    map.merge("my_system_data_duplicateKey", column.value(), (a, b) -> a + "," + b);
                }
            } else {
                map.put(field.getName(), field.getName());
                if(field.isAnnotationPresent(Id.class)) {
                    map.put("my_system_data_id", field.getName());
                }
                if(field.isAnnotationPresent(UniqueKey.class)) {
                    map.put("my_system_data_uniqueKey", field.getName());
                }
                if(field.isAnnotationPresent(AggregateKey.class)) {
                    map.put("my_system_data_aggregateKey", field.getName());
                }
                if(field.isAnnotationPresent(DuplicateKey.class)) {
                    map.merge("my_system_data_duplicateKey", field.getName(), (a, b) -> a + "," + b);
                }
            }
        }
        return map;
    }
}
